/*
 * *******************************************************************
 *   @项目名称: BHex Android
 *   @文件名称: BHexApplication.java
 *   @Date: 18-11-29 下午4:05
 *   @Author: ppzhao
 *   @Description:
 *   @Copyright（C）: 2018 BlueHelix Inc.   All rights reserved.
 *   注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的.
 *  *******************************************************************
 */

package io.bhex.app.app;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.StrictMode;
import android.support.multidex.MultiDex;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;

import com.datatheorem.android.trustkit.TrustKit;
import com.datatheorem.android.trustkit.reporting.BackgroundReporter;
import com.facebook.stetho.Stetho;
import com.github.moduth.blockcanary.BlockCanary;
import com.umeng.analytics.MobclickAgent;

import java.util.HashMap;
import java.util.List;

import io.bhex.app.BuildConfig;
import io.bhex.app.account.utils.LocalManageUtil;
import io.bhex.app.broadcast.receiver.PinningFailureReportBroadcastReceiver;
import io.bhex.app.safe.SafeUilts;
import io.bhex.app.utils.CommonUtil;
import io.bhex.app.utils.IntentUtils;
import io.bhex.app.utils.NetWorkStatus;
import io.bhex.baselib.constant.AppData;
import io.bhex.baselib.core.CApplication;
import io.bhex.baselib.core.SPEx;
import io.bhex.baselib.network.params.UploadParam;
import io.bhex.baselib.utils.DebugLog;
import io.bhex.baselib.utils.DevicesUtil;
import io.bhex.baselib.utils.LogToFile;
import io.bhex.sdk.BhexSdk;
import io.bhex.sdk.Config;
import io.bhex.sdk.UrlsConfig;
import io.bhex.sdk.data_manager.RateAndLocalManager;
import io.bhex.sdk.data_manager.UploadNetRequestManager;

public class BHexApplication extends CApplication {
    private int count=0;
    private Handler mHandler;
    private static final int TIMEOUT_MESSAGE = 0X1;
    public static BHexApplication getInstance() {
        return (BHexApplication) CApplication.getInstance();
    }

    @Override
    public void onCreate() {
        super.onCreate();

        //long t1 = SystemClock.currentThreadTimeMillis();

        //初始化网络安全配置
        //initNetworkSecurityConfig();

        //APP生命周期监听
        registerActivityLife();

        //由于使用了umeng统计，在gradle中加入multiDexEnabled是不够的，需要在application里再调用下，请谨慎删除
        //MultiDex.install(this);

        //APP全局异常捕获 （只有release才进行捕获）
        //catchAppCrash();

        //压后台处理
        backHome();

        //内存分析
        //memeryAnalysis();

        //APP配置初始化
        initAppConfig();

        //设置Cookie监听
        setCookieListener();

        //ToastUtils.Init();

        //上传错误请求日志
        //uploadRequestErrorListener();

        if(BuildConfig.DEBUG){
            BlockCanary.install(this, new AppBlockCanaryContext()).start();
            Stetho.initializeWithDefaults(this);
            //initStrictMode();
        }
        //long t2 = SystemClock.currentThreadTimeMillis();

        /*Log.d("AppConfig:","onCreate 用时:"+(t2-t1));


        Log.d("BHexApplication","BlockCanary==");*/

        if (BuildConfig.DEBUG) {
            //初始化写日志
            LogToFile.init(this);
        }
    }

    private void initStrictMode() {
        StrictMode.setThreadPolicy(
                new StrictMode.ThreadPolicy.Builder()
                        .detectDiskReads()
                        .detectDiskWrites()
                        .detectNetwork().penaltyLog().build());

        StrictMode.setVmPolicy(
                new StrictMode.VmPolicy.Builder().
                        detectLeakedSqlLiteObjects()
                        .detectLeakedClosableObjects()
                        .penaltyLog().penaltyDeath().build());
    }

    /**
     * 上传错误请求日志
     */
    private void uploadRequestErrorListener() {

        if (!BuildConfig.DEBUG) {
            //日志上报（release环境）
            BhexSdk.SetUploadResponseErrorListener(new BhexSdk.OnResponseErrorListener() {

                @Override
                public void OnUploadResponseError(String url, String errorCode) {

                    if(NetWorkStatus.isConnected(BHexApplication.this)) {
                        try {
                            HashMap<String, String> map = new HashMap<String, String>();
                            String urlRequest = url;
                            if(url.contains("?") == true) {
                                urlRequest = url.substring(0, url.indexOf("?"));
                            }
                            String errorMsg = urlRequest + "";
                            if (!TextUtils.isEmpty(errorCode))
                                errorMsg = errorMsg + "__code + " + errorCode;
                            map.put("ResponseError", errorMsg);

                            String domain = UrlsConfig.API_SERVER_URL;
                            domain = domain.replace(':', '_');
                            domain = domain.substring(domain.indexOf("//") + 2, domain.lastIndexOf("/"));
                            MobclickAgent.onEvent(BHexApplication.this, domain + "_ResponseError", map);
                        }
                        catch (Exception e){

                        }
                    }

                }

                @Override
                public void OnUploadNetRequest(UploadParam param) {
                    UploadNetRequestManager.GetInstance().SetUploadRequestParam(param);
                }
            });
        }
    }

    /**
     * 设置Cookie监听
     */
    private void setCookieListener() {
        //需要去登录监听
        BhexSdk.SetNoCookieListener(new BhexSdk.OnNoCookieListener() {
            @Override
            public void OnNoCookie(Context activity, String caller) {
                IntentUtils.goLogin(activity, caller);
            }

            @Override
            public void OnNoCookie(Activity activity, String caller, int requestCode) {
                IntentUtils.goLoginAndDo(activity, caller, requestCode);

            }
        });
    }

    /**
     * APP 配置初始化
     */
    private void initAppConfig() {
        String processName = getProcessName(this);
        DebugLog.d(processName);

        boolean isInMainProcess = !TextUtils.isEmpty(processName) && processName.equals(BuildConfig.APPLICATION_ID);
        if (isInMainProcess) {
            APPConfig.getInstance().initConfig();
        }
    }



    /**
     * 压入后台
     */
    private void backHome() {

        mHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what){
                    case TIMEOUT_MESSAGE:
                        if(AppData.isHome == true){
                            SPEx.setFingerAuth(false);
                            BhexSdk.Stop();
                        }
                        break;
                }
            }
        };
    }

    /**
     * 初始化网络安全配置
     */
    private void initNetworkSecurityConfig() {
        if (CommonUtil.isBhex(this)) {
            TrustKit.initializeWithNetworkSecurityConfiguration(this);
            //Optionally add a local broadcast receiver to receive PinningFailureReports
            PinningFailureReportBroadcastReceiver receiver = new PinningFailureReportBroadcastReceiver();
            LocalBroadcastManager.getInstance(this)
                    .registerReceiver(receiver, new IntentFilter(BackgroundReporter.REPORT_VALIDATION_EVENT));

        }
    }

    /**
     * APP全局异常捕获 （只有release才进行捕获）
     */
    private void catchAppCrash() {
        if (!BuildConfig.DEBUG) {
            CrashHandler.install(new CrashHandler.ExceptionHandler() {
                @Override
                public void handlerException(final Thread thread, final Throwable throwable) {
                    new Handler(Looper.getMainLooper()).post(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                //TODO 用于处理捕获的全局崩溃
                            } catch (Throwable e) {

                            }
                        }
                    });
                }
            });
        }
    }

    /**
     * 生命周期监听
     */
    private void registerActivityLife() {
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

            @Override
            public void onActivityStopped(Activity activity) {
                DebugLog.v("Activity", activity + "onActivityStopped");
                count--;
                if (count == 0) {
                    DebugLog.v("Activity", ">>>>>>>>>>>>>>>>>>>切到后台  lifecycle");
                    if (SafeUilts.isOpenSageVerify()) {
                        AppData.isHome = true;
                        AppData.HOME_TIME = System.currentTimeMillis();
                        if(expiredTime() >0 &&  expiredTime() - System.currentTimeMillis() >0){
                            mHandler.sendEmptyMessageDelayed(TIMEOUT_MESSAGE, expiredTime() - System.currentTimeMillis());
                        }
                    }
                }
            }

            @Override
            public void onActivityStarted(Activity activity) {
                DebugLog.v("BHActivity", activity + "onActivityStarted");
                if (count == 0) {
                    DebugLog.v("Activity", ">>>>>>>>>>>>>>>>>>>切到前台  lifecycle");
                    if(expiredTime() >0 &&  expiredTime() < System.currentTimeMillis() && System.currentTimeMillis() - AppData.HOME_TIME > 5 * 60 * 1000){
                        //ActivityCache.getInstance().finishActivity();
                        SPEx.setFingerAuth(false);
                        BhexSdk.Stop();
                        IntentUtils.goMain(BHexApplication.this);
                    }
                }
                count++;
                //RateAndLocalManager.GetInstance(activity).SetCurLocalKind(activity, RateAndLocalManager.GetInstance(activity).getCurLocalKind());
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
                DebugLog.v("Activity", activity + "切onActivitySaveInstanceState");
            }

            @Override
            public void onActivityResumed(Activity activity) {
                DebugLog.v("Activity", activity + "切onActivityResumed");
                io.bhex.app.app.ActivityManager.getInstance().setCurrentActivity(activity);
            }

            @Override
            public void onActivityPaused(Activity activity) {
                DebugLog.v("Activity", activity + "切onActivityPaused");
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                DebugLog.v("Activity", activity + "切onActivityDestroyed");
                io.bhex.app.app.ActivityManager.getInstance().removeActivity(activity);
            }

            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                DebugLog.v("Activity", activity + "切onActivityCreated");
                io.bhex.app.app.ActivityManager.getInstance().addActivity(activity);
            }
        });

    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        if (!BuildConfig.DEBUG) {
            CrashHandler.uninstall();
        }
    }

    @Override
    protected void attachBaseContext(Context base) {
        BHexApplication.setMBaseContext(base);
        super.attachBaseContext(
                LocalManageUtil.createConfigurationResources(base,
                LocalManageUtil.getSetLanguageLocale(base).getLanguage()));
        RateAndLocalManager.GetInstance(base).initRateKind(base);
        //super.attachBaseContext(base);
        MultiDex.install(this);
    }

    private String getProcessName(Context context) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
        if (runningApps == null) {
            return null;
        }
        for (ActivityManager.RunningAppProcessInfo proInfo : runningApps) {
            if (proInfo.pid == android.os.Process.myPid()) {
                if (proInfo.processName != null) {
                    return proInfo.processName;
                }
            }
        }
        return null;
    }

}
